﻿using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using pinche_api.Data;
using static System.CustomApiVersion;

namespace pinche_api {
    /// <summary>
    /// 拼车小程序API 
    /// </summary>
    public class Startup {

        private readonly string ApiName = "拼车小程序";
        /// <summary>
        /// 
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="hostingEnvironment"></param>
        public Startup(IConfiguration configuration,IHostingEnvironment hostingEnvironment) {
            Configuration=configuration;
            AppConfig.Debug=Utils.GetObjTranNull<bool>(Configuration["Appsetting:Debug"]);
            AppConfig.VirtualFolder=Configuration["Appsetting:VirtualFolder"];

            AppConfig.APPID=Configuration["Appsetting:APPID"];
            AppConfig.AppSecret=Configuration["Appsetting:AppSecret"];
        }
        /// <summary>
        /// 
        /// </summary>
        public IConfiguration Configuration { get; }

        /// <summary>
        /// This method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services"></param>
        public void ConfigureServices(IServiceCollection services) {
            services.AddOptions();
            services.Configure<FormOptions>(o => {
                o.ValueLengthLimit=int.MaxValue;
                o.MultipartBodyLengthLimit=long.MaxValue;
                o.MultipartBoundaryLengthLimit=int.MaxValue;
                o.MultipartHeadersCountLimit=int.MaxValue;
                o.MultipartHeadersLengthLimit=int.MaxValue;
            });
            services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(Directory.GetCurrentDirectory()
              +Path.DirectorySeparatorChar+"DataProtection"));

            services.AddCors(option => option.AddPolicy("cors",policy => policy.AllowAnyHeader().AllowAnyMethod().AllowCredentials().AllowAnyOrigin()));

            services.AddMvc().AddJsonOptions(options => {
                options.SerializerSettings.ReferenceLoopHandling=ReferenceLoopHandling.Ignore;
                options.SerializerSettings.ContractResolver=new DefaultContractResolver();
                options.SerializerSettings.DateFormatString="yyyy-MM-dd HH:mm:ss";
            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddSwaggerGen(options => {
                //遍历出全部的版本，做文档信息展示
                typeof(ApiVersions).GetEnumNames().ToList().ForEach(version => {
                    options.SwaggerDoc(version,new OpenApiInfo {
                        Version=version,
                        Title=$"{ApiName} 接口文档",
                        Description=$"{ApiName} HTTP API "+version
                    });
                });
                //这里注册DocumentFilter
                options.DocumentFilter<AutoHttpMethodOperationFitler>();
                var xmlCommentFile = $@"{Directory.GetCurrentDirectory()}\{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                if(File.Exists(xmlCommentFile)) {
                    options.IncludeXmlComments(xmlCommentFile);
                }
                Logger.LogInfo("接口文档XML描述:"+xmlCommentFile);
                options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
                options.IgnoreObsoleteActions();
                options.IgnoreObsoleteProperties();
            });
            string connecttext = $@"Filename={Directory.GetCurrentDirectory()}\wwwroot\db\carpool.db";
            services.AddDbContext<SQLiteContext>(options => options.UseSqlite(connecttext));
        }

        /// <summary>
        ///  This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        public void Configure(IApplicationBuilder app,IHostingEnvironment env) {
            if(env.IsDevelopment()) {
                app.UseDeveloperExceptionPage();
            }
            app.UseCors("cors");
            app.UseStaticFiles();
            app.UseSwagger();
            app.UseSwaggerUI(options => {
                typeof(ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version => {
                    options.SwaggerEndpoint(AppConfig.VirtualFolder+$"/swagger/{version}/swagger.json",$"{ApiName} {version}");
                });
                options.InjectStylesheet(AppConfig.VirtualFolder+"/swagger-ui/custom.css");
                options.InjectJavascript(AppConfig.VirtualFolder+"/swagger-ui/swagger_cn.js");
                string indexfile = Directory.GetCurrentDirectory()+"/wwwroot/swagger-ui/index.html";
                if(File.Exists(indexfile)) {
                    options.IndexStream=() => File.OpenRead(indexfile);
                }
            });
            app.UseForwardedHeaders(new ForwardedHeadersOptions {
                ForwardedHeaders=ForwardedHeaders.XForwardedFor|ForwardedHeaders.XForwardedProto
            });
            app.UseMvc(routes => {
                routes.MapRoute(
                  name: "areas",
                  template: "{area:exists}/{controller=Text}/{action=Index}/{id?}"
                );
                routes.MapRoute(
                name: "default",
                template: "{controller}/{action}/{id?}",
                defaults: new { controller = "Home",action = "Index" });
            });
        }
    }
}
